<template>
  <div class="list-view">
    <!-- 筛选工具栏 -->
    <div v-if="showToolbar" class="list-toolbar">
      <!-- 搜索框 -->
      <div class="search-box">
        <el-input
          v-model="searchQuery"
          :placeholder="searchPlaceholder"
          clearable
          @input="handleSearch"
        >
          <template #prefix>
            <el-icon><Search /></el-icon>
          </template>
        </el-input>
      </div>

      <!-- 排序选择 -->
      <div class="sort-box">
        <el-select
          v-model="sortOption"
          :placeholder="sortPlaceholder"
          @change="handleSort"
        >
          <el-option
            v-for="option in sortOptions"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-select>
      </div>

      <!-- 布局切换 -->
      <div class="layout-switch">
        <el-radio-group
          v-model="currentLayout"
          size="small"
          @change="handleLayoutChange"
        >
          <el-radio-button value="grid">
            <el-icon><Grid /></el-icon>
          </el-radio-button>
          <el-radio-button value="list">
            <el-icon><List /></el-icon>
          </el-radio-button>
        </el-radio-group>
      </div>

      <!-- 自定义工具栏插槽 -->
      <div class="custom-tools">
        <slot name="tools"></slot>
      </div>
    </div>

    <!-- 筛选标签 -->
    <div v-if="showTags && filterTags.length" class="filter-tags">
      <el-tag
        v-for="tag in filterTags"
        :key="tag.value"
        closable
        @close="handleRemoveTag(tag)"
      >
        {{ tag.label }}
      </el-tag>
      <el-button
        v-if="filterTags.length"
        type="text"
        size="small"
        @click="handleClearTags"
      >
        清除全部
      </el-button>
    </div>

    <!-- 列表内容 -->
    <div
      class="list-content"
      :class="[`layout-${currentLayout}`, { loading: loading }]"
    >
      <!-- 网格布局 -->
      <template v-if="currentLayout === 'grid'">
        <div class="grid-container" :style="gridStyle">
          <div
            v-for="item in filteredItems"
            :key="item.id"
            class="grid-item"
            @click="handleItemClick(item)"
          >
            <slot name="grid-item" :item="item">
              <div class="default-grid-item">
                <div v-if="item.image" class="item-image">
                  <el-image :src="item.image" :alt="item.title" fit="cover" />
                </div>
                <div class="item-content">
                  <h3 class="item-title">{{ item.title }}</h3>
                  <p v-if="item.description" class="item-description">
                    {{ item.description }}
                  </p>
                </div>
              </div>
            </slot>
          </div>
        </div>
      </template>

      <!-- 列表布局 -->
      <template v-else>
        <div class="list-container">
          <div
            v-for="item in filteredItems"
            :key="item.id"
            class="list-item"
            @click="handleItemClick(item)"
          >
            <slot name="list-item" :item="item">
              <div class="default-list-item">
                <div v-if="item.image" class="item-image">
                  <el-image :src="item.image" :alt="item.title" fit="cover" />
                </div>
                <div class="item-content">
                  <h3 class="item-title">{{ item.title }}</h3>
                  <p v-if="item.description" class="item-description">
                    {{ item.description }}
                  </p>
                  <div v-if="item.meta" class="item-meta">
                    <span
                      v-for="(meta, index) in item.meta"
                      :key="index"
                      class="meta-item"
                    >
                      {{ meta }}
                    </span>
                  </div>
                </div>
                <div v-if="$slots['item-actions']" class="item-actions">
                  <slot name="item-actions" :item="item"></slot>
                </div>
              </div>
            </slot>
          </div>
        </div>
      </template>

      <!-- 空状态 -->
      <el-empty v-if="isEmpty" :description="emptyText">
        <template v-if="$slots.empty" #default>
          <slot name="empty"></slot>
        </template>
      </el-empty>

      <!-- 加载状态 -->
      <div v-if="loading" class="loading-mask">
        <el-icon class="loading-icon"><Loading /></el-icon>
        <span>加载中...</span>
      </div>
    </div>

    <!-- 分页 -->
    <div v-if="showPagination" class="list-pagination">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :total="total"
        :page-sizes="pageSizes"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
      />
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from "vue";
import { Search, Grid, List, Loading } from "@element-plus/icons-vue";

const props = defineProps({
  items: {
    type: Array,
    required: true,
  },
  loading: {
    type: Boolean,
    default: false,
  },
  showToolbar: {
    type: Boolean,
    default: true,
  },
  showTags: {
    type: Boolean,
    default: true,
  },
  showPagination: {
    type: Boolean,
    default: true,
  },
  layout: {
    type: String,
    default: "grid",
    validator: (value) => ["grid", "list"].includes(value),
  },
  gridColumns: {
    type: [Number, Object],
    default: 4,
  },
  gridGap: {
    type: [Number, String],
    default: 16,
  },
  sortOptions: {
    type: Array,
    default: () => [
      { label: "默认排序", value: "default" },
      { label: "最新发布", value: "newest" },
      { label: "最多浏览", value: "views" },
    ],
  },
  searchPlaceholder: {
    type: String,
    default: "搜索",
  },
  sortPlaceholder: {
    type: String,
    default: "排序",
  },
  emptyText: {
    type: String,
    default: "暂无数据",
  },
  pageSizes: {
    type: Array,
    default: () => [10, 20, 50, 100],
  },
});

const emit = defineEmits([
  "search",
  "sort",
  "filter",
  "layout-change",
  "item-click",
  "page-change",
  "size-change",
]);

// 状态变量
const searchQuery = ref("");
const sortOption = ref("default");
const currentLayout = ref(props.layout);
const filterTags = ref([]);
const currentPage = ref(1);
const pageSize = ref(props.pageSizes[0]);

// 计算属性
const gridStyle = computed(() => {
  const columns =
    typeof props.gridColumns === "object"
      ? props.gridColumns
      : { default: props.gridColumns };

  const gap =
    typeof props.gridGap === "number" ? `${props.gridGap}px` : props.gridGap;

  return {
    display: "grid",
    gap,
    gridTemplateColumns: `repeat(${columns.default}, minmax(0, 1fr))`,
    "@media (max-width: 1280px)": columns.xl && {
      gridTemplateColumns: `repeat(${columns.xl}, minmax(0, 1fr))`,
    },
    "@media (max-width: 1024px)": columns.lg && {
      gridTemplateColumns: `repeat(${columns.lg}, minmax(0, 1fr))`,
    },
    "@media (max-width: 768px)": columns.md && {
      gridTemplateColumns: `repeat(${columns.md}, minmax(0, 1fr))`,
    },
    "@media (max-width: 640px)": columns.sm && {
      gridTemplateColumns: `repeat(${columns.sm}, minmax(0, 1fr))`,
    },
  };
});

const filteredItems = computed(() => {
  let result = [...props.items];

  // 搜索过滤
  if (searchQuery.value) {
    const query = searchQuery.value.toLowerCase();
    result = result.filter(
      (item) =>
        item.title?.toLowerCase().includes(query) ||
        item.description?.toLowerCase().includes(query),
    );
  }

  // 标签过滤
  if (filterTags.value.length) {
    result = result.filter((item) =>
      filterTags.value.every((tag) => item[tag.field] === tag.value),
    );
  }

  // 排序
  if (sortOption.value !== "default") {
    result.sort((a, b) => {
      switch (sortOption.value) {
        case "newest":
          return new Date(b.createdAt) - new Date(a.createdAt);
        case "views":
          return b.views - a.views;
        default:
          return 0;
      }
    });
  }

  return result;
});

const isEmpty = computed(() => filteredItems.value.length === 0);

const total = computed(() => filteredItems.value.length);

// 事件处理
const handleSearch = () => {
  emit("search", searchQuery.value);
};

const handleSort = () => {
  emit("sort", sortOption.value);
};

const handleLayoutChange = () => {
  emit("layout-change", currentLayout.value);
};

const handleItemClick = (item) => {
  emit("item-click", item);
};

const handleRemoveTag = (tag) => {
  filterTags.value = filterTags.value.filter((t) => t.value !== tag.value);
  emit("filter", filterTags.value);
};

const handleClearTags = () => {
  filterTags.value = [];
  emit("filter", filterTags.value);
};

const handlePageChange = (page) => {
  currentPage.value = page;
  emit("page-change", page);
};

const handleSizeChange = (size) => {
  pageSize.value = size;
  emit("size-change", size);
};

// 对外暴露方法
defineExpose({
  addFilterTag: (tag) => {
    if (!filterTags.value.some((t) => t.value === tag.value)) {
      filterTags.value.push(tag);
      emit("filter", filterTags.value);
    }
  },
  clearFilters: () => {
    filterTags.value = [];
    emit("filter", filterTags.value);
  },
  reset: () => {
    searchQuery.value = "";
    sortOption.value = "default";
    filterTags.value = [];
    currentPage.value = 1;
    pageSize.value = props.pageSizes[0];
  },
});
</script>

<style lang="scss" scoped>
.list-view {
  @apply w-full;

  .list-toolbar {
    @apply flex flex-wrap items-center gap-4 mb-4;

    .search-box {
      @apply flex-1 min-w-[200px];
    }

    .sort-box {
      @apply w-40;
    }

    .layout-switch {
      @apply flex items-center;
    }

    .custom-tools {
      @apply flex items-center gap-2;
    }
  }

  .filter-tags {
    @apply flex flex-wrap items-center gap-2 mb-4;
  }

  .list-content {
    @apply relative min-h-[200px];

    &.layout-grid {
      .grid-container {
        @apply w-full;

        .grid-item {
          @apply cursor-pointer transition-transform hover:scale-[1.02];
        }

        .default-grid-item {
          @apply bg-white rounded-lg overflow-hidden shadow-sm;

          .item-image {
            @apply aspect-square;

            :deep(.el-image) {
              @apply w-full h-full;
            }
          }

          .item-content {
            @apply p-4;

            .item-title {
              @apply text-lg font-medium text-gray-900 mb-2 line-clamp-1;
            }

            .item-description {
              @apply text-sm text-gray-600 line-clamp-2;
            }
          }
        }
      }
    }

    &.layout-list {
      .list-container {
        @apply space-y-4;

        .list-item {
          @apply cursor-pointer;
        }

        .default-list-item {
          @apply flex gap-4 bg-white rounded-lg p-4 transition-colors hover:bg-gray-50;

          .item-image {
            @apply w-40 h-40 flex-shrink-0 rounded-lg overflow-hidden;

            :deep(.el-image) {
              @apply w-full h-full;
            }
          }

          .item-content {
            @apply flex-1 min-w-0;

            .item-title {
              @apply text-xl font-medium text-gray-900 mb-2;
            }

            .item-description {
              @apply text-gray-600 mb-4 line-clamp-2;
            }

            .item-meta {
              @apply flex items-center gap-4 text-sm text-gray-500;

              .meta-item {
                @apply flex items-center gap-1;
              }
            }
          }

          .item-actions {
            @apply flex items-center gap-2;
          }
        }
      }
    }
  }

  .loading-mask {
    @apply absolute inset-0 flex flex-col items-center justify-center bg-white bg-opacity-90;

    .loading-icon {
      @apply text-2xl text-primary-600 animate-spin mb-2;
    }
  }

  .list-pagination {
    @apply mt-6 flex justify-center;
  }
}
</style>
